home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / BBOX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-02  |  38.3 KB  |  1,919 lines

  1. /*****************************************************************************
  2. *                bbox.c
  3. *
  4. *  This module implements the bounding box calculations.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  POV-Ray's bounding boxes and generously provided us these enhancements.
  7. *  The box intersection code was further hacked by Eric Haines to speed it up.
  8. *
  9. *  Just so everyone knows where this came from, the code is VERY heavily
  10. *  based on the slab code from Mark VandeWettering's MTV raytracer.
  11. *  POV-Ray is just joining the crowd of admirers of Mark's contribution to
  12. *  the public domain. [ARE]
  13. *
  14. *  from Persistence of Vision(tm) Ray Tracer
  15. *  Copyright 1996 Persistence of Vision Team
  16. *---------------------------------------------------------------------------
  17. *  NOTICE: This source code file is provided so that users may experiment
  18. *  with enhancements to POV-Ray and to port the software to platforms other
  19. *  than those supported by the POV-Ray Team.  There are strict rules under
  20. *  which you are permitted to use this file.  The rules are in the file
  21. *  named POVLEGAL.DOC which should be distributed with this file. If
  22. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  23. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  24. *  Forum.  The latest version of POV-Ray may be found there as well.
  25. *
  26. * This program is based on the popular DKB raytracer version 2.12.
  27. * DKBTrace was originally written by David K. Buck.
  28. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  29. *
  30. *****************************************************************************/
  31.  
  32. #include "frame.h"
  33. #include "vector.h"
  34. #include "povproto.h"
  35. #include "bbox.h"
  36. #include "matrices.h"
  37. #include "objects.h"
  38. #include "povray.h"
  39. #include "render.h"
  40.  
  41.  
  42.  
  43. /*****************************************************************************
  44. * Local preprocessor defines
  45. ******************************************************************************/
  46.  
  47. #define BUNCHING_FACTOR 4
  48.  
  49. /* Initial number of entries in a priority queue. */
  50.  
  51. #define INITIAL_PRIORITY_QUEUE_SIZE 256
  52.  
  53.  
  54.  
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58.  
  59.  
  60.  
  61. /*****************************************************************************
  62. * Static functions
  63. ******************************************************************************/
  64.  
  65. static BBOX_TREE *create_bbox_node PARAMS((int size));
  66.  
  67. static int find_axis PARAMS((BBOX_TREE **Finite, long first, long last));
  68. static void calc_bbox PARAMS((BBOX *BBox, BBOX_TREE **Finite, long first, long last));
  69. static void build_area_table PARAMS((BBOX_TREE **Finite, long a, long b, DBL *areas));
  70. static int sort_and_split PARAMS((BBOX_TREE **Root, BBOX_TREE **Finite, long *nFinite, long first, long last));
  71.  
  72. static void priority_queue_insert PARAMS((PRIORITY_QUEUE *Queue, DBL Depth, BBOX_TREE *Node));
  73.  
  74. static int CDECL compboxes PARAMS((CONST void *in_a, CONST void *in_b));
  75.  
  76.  
  77. /*****************************************************************************
  78. * Local variables
  79. ******************************************************************************/
  80.  
  81. /* Current axis to sort along. */
  82.  
  83. static int Axis = 0;
  84.  
  85. /* Number of finite elements. */
  86.  
  87. static long maxfinitecount = 0;
  88.  
  89. /* Priority queue used for frame level bouning box hierarchy. */
  90.  
  91. static PRIORITY_QUEUE *Frame_Queue;
  92.  
  93. /* Top node of bounding hierarchy. */
  94.  
  95. BBOX_TREE *Root_Object;
  96.  
  97.  
  98.  
  99. /*****************************************************************************
  100. *
  101. * FUNCTION
  102. *
  103. *   Initialize_BBox_Code
  104. *
  105. * INPUT
  106. *
  107. * OUTPUT
  108. *
  109. * RETURNS
  110. *
  111. * AUTHOR
  112. *
  113. *   Dieter Bayer
  114. *
  115. * DESCRIPTION
  116. *
  117. *   Initialize bbox specific variables.
  118. *
  119. * CHANGES
  120. *
  121. *   Jul 1995 : Creation.
  122. *
  123. ******************************************************************************/
  124.  
  125. void Initialize_BBox_Code()
  126. {
  127.   Frame_Queue = Create_Priority_Queue(INITIAL_PRIORITY_QUEUE_SIZE);
  128. }
  129.  
  130.  
  131.  
  132. /*****************************************************************************
  133. *
  134. * FUNCTION
  135. *
  136. *   Deinitialize_BBox_Code
  137. *
  138. * INPUT
  139. *
  140. * OUTPUT
  141. *
  142. * RETURNS
  143. *
  144. * AUTHOR
  145. *
  146. *   Dieter Bayer
  147. *
  148. * DESCRIPTION
  149. *
  150. *   Deinitialize bbox specific variables.
  151. *
  152. * CHANGES
  153. *
  154. *   Jul 1995 : Creation.
  155. *
  156. ******************************************************************************/
  157.  
  158. void Deinitialize_BBox_Code()
  159. {
  160.   if (Frame_Queue != NULL)
  161.   {
  162.     Destroy_Priority_Queue(Frame_Queue);
  163.   }
  164.  
  165.   Frame_Queue = NULL;
  166. }
  167.  
  168.  
  169.  
  170. /*****************************************************************************
  171. *
  172. * FUNCTION
  173. *
  174. *   Create_Priority_Queue
  175. *
  176. * INPUT
  177. *
  178. *   QSize - initial size of priority queue
  179. *
  180. * OUTPUT
  181. *
  182. * RETURNS
  183. *
  184. *   PRIORITY_QUEUE * - priority queue
  185. *
  186. * AUTHOR
  187. *
  188. *   Dieter Bayer
  189. *
  190. * DESCRIPTION
  191. *
  192. *   Create a priority queue.
  193. *
  194. * CHANGES
  195. *
  196. *   Feb 1995 : Creation.
  197. *
  198. ******************************************************************************/
  199.  
  200. PRIORITY_QUEUE *Create_Priority_Queue(QSize)
  201. unsigned QSize;
  202. {
  203.   PRIORITY_QUEUE *New;
  204.  
  205.   New = (PRIORITY_QUEUE *)POV_MALLOC(sizeof(PRIORITY_QUEUE), "priority queue");
  206.  
  207.   New->Queue = (QELEM *)POV_MALLOC(QSize*sizeof(QELEM), "priority queue");
  208.  
  209.   New->QSize = 0;
  210.  
  211.   New->Max_QSize = QSize;
  212.  
  213.   return (New);
  214. }
  215.  
  216.  
  217.  
  218. /*****************************************************************************
  219. *
  220. * FUNCTION
  221. *
  222. *   Destroy_Priority_Queue
  223. *
  224. * INPUT
  225. *
  226. *   Queue - Priority queue
  227. *
  228. * OUTPUT
  229. *
  230. * RETURNS
  231. *
  232. * AUTHOR
  233. *
  234. *   Dieter Bayer
  235. *
  236. * DESCRIPTION
  237. *
  238. *   Destroy a priority queue.
  239. *
  240. * CHANGES
  241. *
  242. *   Feb 1995 : Creation.
  243. *
  244. ******************************************************************************/
  245.  
  246. void Destroy_Priority_Queue(Queue)
  247. PRIORITY_QUEUE *Queue;
  248. {
  249.   if (Queue != NULL)
  250.   {
  251.     POV_FREE(Queue->Queue);
  252.  
  253.     POV_FREE(Queue);
  254.   }
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************
  260. *
  261. * FUNCTION
  262. *
  263. *   Destroy_BBox_Tree
  264. *
  265. * INPUT
  266. *
  267. *   Node - Node to destroy
  268. *
  269. * OUTPUT
  270. *
  271. * RETURNS
  272. *
  273. * AUTHOR
  274. *
  275. *   Dieter Bayer
  276. *
  277. * DESCRIPTION
  278. *
  279. *   Recursively destroy a bounding box tree.
  280. *
  281. * CHANGES
  282. *
  283. *   -
  284. *
  285. ******************************************************************************/
  286.  
  287. void Destroy_BBox_Tree(Node)
  288. BBOX_TREE *Node;
  289. {
  290.   short i;
  291.  
  292.   if (Node != NULL)
  293.   {
  294.     if (Node->Entries > 0)
  295.     {
  296.       for (i = 0; i < Node->Entries; i++)
  297.       {
  298.         Destroy_BBox_Tree(Node->Node[i]);
  299.       }
  300.  
  301.       POV_FREE(Node->Node);
  302.  
  303.       Node->Entries = 0;
  304.  
  305.       Node->Node = NULL;
  306.     }
  307.  
  308.     POV_FREE(Node);
  309.   }
  310. }
  311.  
  312.  
  313.  
  314. /*****************************************************************************
  315. *
  316. * FUNCTION
  317. *
  318. *   Recompute_BBox
  319. *
  320. * INPUT
  321. *
  322. *   trans - Transformation
  323. *
  324. * OUTPUT
  325. *
  326. *   bbox  - Bounding box
  327. *
  328. * RETURNS
  329. *
  330. * AUTHOR
  331. *
  332. *   Alexander Enzmann
  333. *
  334. * DESCRIPTION
  335. *
  336. *   Recalculate a bounding box after a transformation.
  337. *
  338. * CHANGES
  339. *
  340. *   -
  341. *
  342. ******************************************************************************/
  343.  
  344. void Recompute_BBox(bbox, trans)
  345. BBOX *bbox;
  346. TRANSFORM *trans;
  347. {
  348.   int i;
  349.   VECTOR lower_left, lengths, corner;
  350.   VECTOR mins, maxs;
  351.  
  352.   if (trans == NULL)
  353.   {
  354.     return;
  355.   }
  356.  
  357.   Assign_BBox_Vect(lower_left, bbox->Lower_Left);
  358.   Assign_BBox_Vect(lengths, bbox->Lengths);
  359.  
  360.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  361.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  362.  
  363.   for (i = 1; i <= 8; i++)
  364.   {
  365.     Assign_Vector(corner, lower_left);
  366.  
  367.     corner[X] += ((i & 1) ? lengths[X] : 0.0);
  368.     corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
  369.     corner[Z] += ((i & 4) ? lengths[Z] : 0.0);
  370.  
  371.     MTransPoint(corner, corner, trans);
  372.  
  373.     if (corner[X] < mins[X]) { mins[X] = corner[X]; }
  374.     if (corner[X] > maxs[X]) { maxs[X] = corner[X]; }
  375.     if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
  376.     if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
  377.     if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
  378.     if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
  379.   }
  380.  
  381.   /* Clip bounding box at the largest allowed bounding box. */
  382.  
  383.   if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
  384.   if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
  385.   if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
  386.   if (maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
  387.   if (maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
  388.   if (maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_HUGE / 2; }
  389.  
  390.   Make_BBox_from_min_max(*bbox, mins, maxs);
  391. }
  392.  
  393.  
  394.  
  395. /*****************************************************************************
  396. *
  397. * FUNCTION
  398. *
  399. *   Recompute_Inverse_BBox
  400. *
  401. * INPUT
  402. *
  403. *   trans - Transformation
  404. *
  405. * OUTPUT
  406. *
  407. *   bbox  - Bounding box
  408. *
  409. * RETURNS
  410. *
  411. * AUTHOR
  412. *
  413. *   Alexander Enzmann
  414. *
  415. * DESCRIPTION
  416. *
  417. *   Recalculate a bounding box after a transformation.
  418. *
  419. * CHANGES
  420. *
  421. *   -
  422. *
  423. ******************************************************************************/
  424.  
  425. void Recompute_Inverse_BBox(bbox, trans)
  426. BBOX *bbox;
  427. TRANSFORM *trans;
  428. {
  429.   int i;
  430.   VECTOR lower_left, lengths, corner;
  431.   VECTOR mins, maxs;
  432.  
  433.   if (trans == NULL)
  434.   {
  435.     return;
  436.   }
  437.  
  438.   Assign_BBox_Vect(lower_left, bbox->Lower_Left);
  439.   Assign_BBox_Vect(lengths, bbox->Lengths);
  440.  
  441.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  442.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  443.  
  444.   for (i = 1; i <= 8; i++)
  445.   {
  446.     Assign_Vector(corner, lower_left);
  447.  
  448.     corner[X] += ((i & 1) ? lengths[X] : 0.0);
  449.     corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
  450.     corner[Z] += ((i & 4) ? lengths[Z] : 0.0);
  451.  
  452.     MInvTransPoint(corner, corner, trans);
  453.  
  454.     if (corner[X] < mins[X]) { mins[X] = corner[X]; }
  455.     if (corner[X] > maxs[X]) { maxs[X] = corner[X]; }
  456.     if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
  457.     if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
  458.     if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
  459.     if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
  460.   }
  461.  
  462.   /* Clip bounding box at the largest allowed bounding box. */
  463.  
  464.   if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
  465.   if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
  466.   if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
  467.   if (maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
  468.   if (maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
  469.   if (maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_HUGE / 2; }
  470.  
  471.   Make_BBox_from_min_max(*bbox, mins, maxs);
  472. }
  473.  
  474.  
  475.  
  476. /*****************************************************************************
  477. *
  478. * FUNCTION
  479. *
  480. *   Build_BBox_Tree
  481. *
  482. * INPUT
  483. *   
  484. * OUTPUT
  485. *   
  486. * RETURNS
  487. *   
  488. * AUTHOR
  489. *
  490. *   Dieter Bayer
  491. *   
  492. * DESCRIPTION
  493. *
  494. *   Create a bounding box hierarchy from a given list of finite and
  495. *   infinite elements. Each element consists of
  496. *
  497. *     - an infinite flag
  498. *     - a bounding box enclosing the element
  499. *     - a pointer to the structure representing the element (e.g an object)
  500. *
  501. * CHANGES
  502. *
  503. *   Feb 1995 : Creation. (Extracted from Build_Bounding_Slabs)
  504. *   Sep 1995 : Changed to allow use of memcpy if memmove isn't available. [AED]
  505. *
  506. ******************************************************************************/
  507.  
  508. void Build_BBox_Tree(Root, nFinite, Finite, nInfinite, Infinite)
  509. BBOX_TREE **Root;
  510. long nFinite, nInfinite;
  511. BBOX_TREE **Finite, **Infinite;
  512. {
  513.   short i;
  514.   long low, high;
  515.   BBOX_TREE *cd, *root;
  516.  
  517.   /*
  518.    * This is a resonable guess at the number of finites needed.
  519.    * This array will be reallocated as needed if it isn't.
  520.    */
  521.  
  522.   maxfinitecount = 2 * nFinite;
  523.  
  524.   /*
  525.    * Now do a sort on the objects, with the end result being
  526.    * a tree of objects sorted along the x, y, and z axes.
  527.    */
  528.  
  529.   if (nFinite > 0)
  530.   {
  531.     low = 0;
  532.     high = nFinite;
  533.  
  534.     while (sort_and_split(Root, Finite, &nFinite, low, high) == 0)
  535.     {
  536.       low = high;
  537.       high = nFinite;
  538.     }
  539.  
  540.     /* Move infinite objects in the first leaf of Root. */
  541.  
  542.     if (nInfinite > 0)
  543.     {
  544. #ifdef NO_MEMMOVE
  545.       int memcnt;
  546. #endif
  547.  
  548.       root = (BBOX_TREE *)(*Root);
  549.  
  550.       root->Node = (BBOX_TREE **)POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite");
  551.  
  552. #ifdef NO_MEMMOVE
  553.       for (memcnt = root->Entries; memcnt > 0; memcnt--)
  554.       {
  555.         memcpy(&(root->Node[memcnt]), &(root->Node[memcnt-1]), sizeof(BBOX_TREE *));
  556.       }
  557. #else /* have MEMMOVE */
  558.       memmove(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *));
  559. #endif
  560.  
  561.       root->Entries++;
  562.  
  563.       cd = create_bbox_node(nInfinite);
  564.  
  565.       for (i = 0; i < nInfinite; i++)
  566.       {
  567.         cd->Node[i] = Infinite[i];
  568.       }
  569.  
  570.       calc_bbox(&(cd->BBox), Infinite, 0, nInfinite);
  571.  
  572.       root->Node[0] = (BBOX_TREE *)cd;
  573.  
  574.       calc_bbox(&(root->BBox), root->Node, 0, root->Entries);
  575.  
  576.       /* Root and first node are infinite. */
  577.  
  578.       root->Infinite = TRUE;
  579.  
  580.       root->Node[0]->Infinite = TRUE;
  581.     }
  582.   }
  583.   else
  584.   {
  585.     /*
  586.      * There are no finite objects and no Root was created.
  587.      * Create it now and put all infinite objects into it.
  588.      */
  589.  
  590.     if (nInfinite > 0)
  591.     {
  592.       cd = create_bbox_node(nInfinite);
  593.  
  594.       for (i = 0; i < nInfinite; i++)
  595.       {
  596.         cd->Node[i] = Infinite[i];
  597.       }
  598.  
  599.       calc_bbox(&(cd->BBox), Infinite, 0, nInfinite);
  600.  
  601.       *Root = (BBOX_TREE *)cd;
  602.  
  603.       (*Root)->Infinite = TRUE;
  604.     }
  605.   }
  606. }
  607.  
  608.  
  609.  
  610. /*****************************************************************************
  611. *
  612. * FUNCTION
  613. *
  614. *   Build_Bounding_Slabs
  615. *
  616. * INPUT
  617. *   
  618. * OUTPUT
  619. *   
  620. * RETURNS
  621. *
  622. * AUTHOR
  623. *
  624. *   Alexander Enzmann
  625. *   
  626. * DESCRIPTION
  627. *
  628. *   Create the bounding box hierarchy for all objects in the scene.
  629. *
  630. * CHANGES
  631. *
  632. *   Sep 1994 : Added allocation of priority queue. [DB]
  633. *
  634. *   Sep 1994 : Added code to put all infinite objects in the first node
  635. *              of the root. Thus the hierarchy won't be messed up. [DB]
  636. *
  637. *   Sep 1994 : Fixed nIfinite=0 bug. [DB]
  638. *
  639. *   Feb 1995 : Moved code to actually build the hierarchy. [DB]
  640. *
  641. ******************************************************************************/
  642.  
  643. void Build_Bounding_Slabs(Root)
  644. BBOX_TREE **Root;
  645. {
  646.   long i, nFinite, nInfinite, iFinite, iInfinite;
  647.   BBOX_TREE **Finite, **Infinite;
  648.   OBJECT *Object, *Temp;
  649.  
  650.   /* Count frame level and infinite objects. */
  651.  
  652.   Object = Frame.Objects;
  653.  
  654.   nFinite = nInfinite = 0;
  655.  
  656.   while (Object != NULL)
  657.   {
  658.     if (Object->Type & LIGHT_SOURCE_OBJECT)
  659.     {
  660.       Temp = ((LIGHT_SOURCE *)Object)->Children;
  661.     }
  662.     else
  663.     {
  664.       Temp = Object;
  665.     }
  666.  
  667.     if (Temp != NULL)
  668.     {
  669.       if (Test_Flag(Temp, INFINITE_FLAG))
  670.       {
  671.         nInfinite++;
  672.       }
  673.       else
  674.       {
  675.         nFinite++;
  676.       }
  677.     }
  678.  
  679.     Object = Object->Sibling;
  680.   }
  681.  
  682.   /* We want to know how many objects there are. */
  683.  
  684.   Render_Info("\nScene contains %ld frame level objects; %ld infinite.\n",
  685.       nFinite + nInfinite, nInfinite);
  686.  
  687.   /* If bounding boxes aren't used we can return. */
  688.  
  689.   if (!opts.Use_Slabs || !(nFinite + nInfinite >= opts.BBox_Threshold))
  690.   {
  691.     opts.Use_Slabs = FALSE; 
  692.  
  693.     return;
  694.   }
  695.  
  696.   opts.Use_Slabs = TRUE;
  697.  
  698.   /*
  699.    * This is a resonable guess at the number of finites needed.
  700.    * This array will be reallocated as needed if it isn't.
  701.    */
  702.  
  703.   maxfinitecount = 2 * nFinite;
  704.  
  705.   /*
  706.    * Now allocate an array to hold references to these finites and
  707.    * any new composite objects we may generate.
  708.    */
  709.  
  710.   Finite = Infinite = NULL;
  711.  
  712.   if (nFinite > 0)
  713.   {
  714.     Finite = (BBOX_TREE **)POV_MALLOC(maxfinitecount*sizeof(BBOX_TREE *), "bounding boxes");
  715.   }
  716.  
  717.   /* Create array to hold pointers to infinite objects. */
  718.  
  719.   if (nInfinite > 0)
  720.   {
  721.     Infinite = (BBOX_TREE **)POV_MALLOC(nInfinite*sizeof(BBOX_TREE *), "bounding boxes");
  722.   }
  723.  
  724.   /* Init lists. */
  725.  
  726.   for (i = 0; i < nFinite; i++)
  727.   {
  728.     Finite[i] = create_bbox_node(0);
  729.   }
  730.  
  731.   for (i = 0; i < nInfinite; i++)
  732.   {
  733.     Infinite[i] = create_bbox_node(0);
  734.   }
  735.  
  736.   /* Set up finite and infinite object lists. */
  737.  
  738.   iFinite = iInfinite = 0;
  739.  
  740.   for (Object = Frame.Objects; Object != NULL; Object = Object->Sibling)
  741.   {
  742.     if (Object->Type & LIGHT_SOURCE_OBJECT)
  743.     {
  744.       Temp = ((LIGHT_SOURCE *)Object)->Children;
  745.     }
  746.     else
  747.     {
  748.       Temp = Object;
  749.     }
  750.  
  751.     if (Temp != NULL)
  752.     {
  753.       /* Add object to the appropriate list. */
  754.  
  755.       if (Test_Flag(Temp, INFINITE_FLAG))
  756.       {
  757.         Infinite[iInfinite]->Infinite = TRUE;
  758.         Infinite[iInfinite]->BBox     = Temp->BBox;
  759.         Infinite[iInfinite]->Node     = (BBOX_TREE **)Temp;
  760.  
  761.         iInfinite++;
  762.       }
  763.       else
  764.       {
  765.         Finite[iFinite]->BBox = Temp->BBox;
  766.         Finite[iFinite]->Node = (BBOX_TREE **)Temp;
  767.  
  768.         iFinite++;
  769.       }
  770.     }
  771.   }
  772.  
  773.   /*
  774.    * Now build the bounding box tree.
  775.    */
  776.  
  777.   Build_BBox_Tree(Root, nFinite, Finite, nInfinite, Infinite);
  778.  
  779.   /* Get rid of the Finite and Infinite arrays and just use Root. */
  780.  
  781.   if (Finite != NULL)
  782.   {
  783.     POV_FREE(Finite);
  784.   }
  785.  
  786.   if (Infinite != NULL)
  787.   {
  788.     POV_FREE(Infinite);
  789.   }
  790. }
  791.  
  792.  
  793.  
  794. /*****************************************************************************
  795. *
  796. * FUNCTION
  797. *
  798. *   Destroy_Bounding_Slabs
  799. *
  800. * INPUT
  801. *
  802. * OUTPUT
  803. *
  804. * RETURNS
  805. *
  806. * AUTHOR
  807. *
  808. *   Alexander Enzmann
  809. *
  810. * DESCRIPTION
  811. *
  812. *   Destroy the bounding box hierarchy and the priority queue.
  813. *
  814. * CHANGES
  815. *
  816. *   Sep 1994 : Added freeing of priority queue. [DB]
  817. *
  818. ******************************************************************************/
  819.  
  820. void Destroy_Bounding_Slabs()
  821. {
  822.   if (Root_Object != NULL)
  823.   {
  824.     Destroy_BBox_Tree(Root_Object);
  825.  
  826.     Root_Object = NULL;
  827.   }
  828. }
  829.  
  830.  
  831.  
  832. /*****************************************************************************
  833. *
  834. * FUNCTION
  835. *
  836. *   Intersect_BBox_Tree
  837. *
  838. * INPUT
  839. *
  840. *   Root - Root node of the bbox tree
  841. *   Ray  - Current ray
  842. *
  843. * OUTPUT
  844. *
  845. *   Best_Intersection - Nearest intersection found
  846. *   Best_Object       - Nearest object found
  847. *
  848. * RETURNS
  849. *
  850. *   int - TRUE if an intersection was found
  851. *
  852. * AUTHOR
  853. *
  854. *   Alexander Enzmann
  855. *
  856. * DESCRIPTION
  857. *
  858. *   Intersect a ray with a bounding box tree.
  859. *
  860. * CHANGES
  861. *
  862. *   Sep 1994 : Moved priority queue allocation/freeing out of here. [DB]
  863. *
  864. ******************************************************************************/
  865.  
  866. int Intersect_BBox_Tree(Root, Ray, Best_Intersection, Best_Object)
  867. BBOX_TREE *Root;
  868. RAY *Ray;
  869. INTERSECTION *Best_Intersection;
  870. OBJECT **Best_Object;
  871. {
  872.   int i, found;
  873.   DBL Depth;
  874.   BBOX_TREE *Node;
  875.   RAYINFO rayinfo;
  876.   INTERSECTION New_Intersection;
  877.  
  878.   /* Create the direction vectors for this ray. */
  879.  
  880.   Create_Rayinfo(Ray, &rayinfo);
  881.  
  882.   /* Start with an empty priority queue. */
  883.  
  884.   found = FALSE;
  885.  
  886.   Frame_Queue->QSize = 0;
  887.  
  888. #ifdef BBOX_EXTRA_STATS
  889.   Increase_Counter(stats[totalQueueResets]);
  890. #endif
  891.  
  892.   /* Check top node. */
  893.  
  894.   Check_And_Enqueue(Frame_Queue, Root, &Root->BBox, &rayinfo);
  895.  
  896.   /* Check elements in the priority queue. */
  897.  
  898.   while (Frame_Queue->QSize)
  899.   {
  900.     Priority_Queue_Delete(Frame_Queue, &Depth, &Node);
  901.  
  902.     /*
  903.      * If current intersection is larger than the best intersection found
  904.      * so far our task is finished, because all other bounding boxes in
  905.      * the priority queue are further away.
  906.      */
  907.  
  908.     if (Depth > Best_Intersection->Depth)
  909.     {
  910.       break;
  911.     }
  912.  
  913.     /* Check current node. */
  914.  
  915.     if (Node->Entries)
  916.     {
  917.       /* This is a node containing leaves to be checked. */
  918.  
  919.       for (i = 0; i < Node->Entries; i++)
  920.       {
  921.         Check_And_Enqueue(Frame_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo);
  922.       }
  923.     }
  924.     else
  925.     {
  926.       /* This is a leaf so test contained object. */
  927.  
  928.       if (Intersection(&New_Intersection, (OBJECT *)Node->Node, Ray))
  929.       {
  930.         if (New_Intersection.Depth < Best_Intersection->Depth)
  931.         {
  932.           *Best_Intersection = New_Intersection;
  933.  
  934.           *Best_Object = (OBJECT *)Node->Node;
  935.  
  936.           found = TRUE;
  937.         }
  938.       }
  939.     }
  940.   }
  941.  
  942.   return (found);
  943. }
  944.  
  945.  
  946.  
  947. /*****************************************************************************
  948. *
  949. * FUNCTION
  950. *
  951. *   priority_queue_insert
  952. *
  953. * INPUT
  954. *   
  955. * OUTPUT
  956. *   
  957. * RETURNS
  958. *   
  959. * AUTHOR
  960. *
  961. *   Alexander Enzmann
  962. *   
  963. * DESCRIPTION
  964. *
  965. *   Insert an element in the priority queue.
  966. *
  967. * CHANGES
  968. *
  969. *   Sep 1994 : Added code for resizing the priority queue. [DB]
  970. *
  971. ******************************************************************************/
  972.  
  973. static void priority_queue_insert(Queue, Depth, Node)
  974. PRIORITY_QUEUE *Queue;
  975. DBL Depth;
  976. BBOX_TREE *Node;
  977. {
  978.   unsigned size;
  979.   int i;
  980.   QELEM tmp, *List;
  981.  
  982. #ifdef BBOX_EXTRA_STATS
  983.   Increase_Counter(stats[totalQueues]);
  984. #endif
  985.  
  986.   Queue->QSize++;
  987.  
  988.   size = Queue->QSize;
  989.  
  990.   /* Reallocate priority queue if it's too small. */
  991.  
  992.   if (size >= Queue->Max_QSize)
  993.   {
  994.     if (size >= INT_MAX/2)
  995.     {
  996.       Error("Priority queue overflow.\n");
  997.     }
  998.  
  999. #ifdef BBOX_EXTRA_STATS
  1000.     Increase_Counter(stats[totalQueueResizes]);
  1001. #endif
  1002.  
  1003.     Queue->Max_QSize *= 2;
  1004.  
  1005.     Queue->Queue = (QELEM *)POV_REALLOC(Queue->Queue, Queue->Max_QSize*sizeof(QELEM), "priority queue");
  1006.   }
  1007.  
  1008.   List = Queue->Queue;
  1009.   
  1010.   List[size].Depth = Depth;
  1011.   List[size].Node  = Node;
  1012.   
  1013.   i = size;
  1014.   
  1015.   while (i > 1 && List[i].Depth < List[i / 2].Depth)
  1016.   {
  1017.     tmp = List[i];
  1018.  
  1019.     List[i] = List[i / 2];
  1020.  
  1021.     List[i / 2] = tmp;
  1022.  
  1023.     i = i / 2;
  1024.   }
  1025. }
  1026.  
  1027.  
  1028.  
  1029. /*****************************************************************************
  1030. *
  1031. * FUNCTION
  1032. *
  1033. *   Priority_Queue_Delete
  1034. *
  1035. * INPUT
  1036. *
  1037. * OUTPUT
  1038. *   
  1039. * RETURNS
  1040. *   
  1041. * AUTHOR
  1042. *
  1043. *   Alexander Enzmann
  1044. *   
  1045. * DESCRIPTION
  1046. *
  1047. *   Get an element from the priority queue.
  1048. *
  1049. *   NOTE: This element will always be the one closest to the ray origin.
  1050. *
  1051. * CHANGES
  1052. *
  1053. *   -
  1054. *
  1055. ******************************************************************************/
  1056.  
  1057. void Priority_Queue_Delete(Queue, Depth, Node)
  1058. PRIORITY_QUEUE *Queue;
  1059. DBL *Depth;
  1060. BBOX_TREE **Node;
  1061. {
  1062.   QELEM tmp, *List;
  1063.   int i, j;
  1064.   unsigned size;
  1065.  
  1066.   if (Queue->QSize == 0)
  1067.   {
  1068.     Error("priority queue is empty.\n");
  1069.   }
  1070.  
  1071.   List = Queue->Queue;
  1072.  
  1073.   *Depth = List[1].Depth;
  1074.   *Node  = List[1].Node;
  1075.  
  1076.   List[1] = List[Queue->QSize];
  1077.  
  1078.   Queue->QSize--;
  1079.  
  1080.   size = Queue->QSize;
  1081.  
  1082.   i = 1;
  1083.  
  1084.   while (2 * i <= (int)size)
  1085.   {
  1086.     if (2 * i == (int)size)
  1087.     {
  1088.       j = 2 * i;
  1089.     }
  1090.     else
  1091.     {
  1092.       if (List[2*i].Depth < List[2*i+1].Depth)
  1093.       {
  1094.         j = 2 * i;
  1095.       }
  1096.       else
  1097.       {
  1098.         j = 2 * i + 1;
  1099.       }
  1100.     }
  1101.  
  1102.     if (List[i].Depth > List[j].Depth)
  1103.     {
  1104.       tmp = List[i];
  1105.  
  1106.       List[i] = List[j];
  1107.  
  1108.       List[j] = tmp;
  1109.  
  1110.       i = j;
  1111.     }
  1112.     else
  1113.     {
  1114.       break;
  1115.     }
  1116.   }
  1117. }
  1118.  
  1119.  
  1120.  
  1121. /*****************************************************************************
  1122. *
  1123. * FUNCTION
  1124. *
  1125. *   Check_And_Enqueue
  1126. *
  1127. * INPUT
  1128. *
  1129. * OUTPUT
  1130. *
  1131. * RETURNS
  1132. *
  1133. * AUTHOR
  1134. *
  1135. *   Alexander Enzmann
  1136. *
  1137. * DESCRIPTION
  1138. *
  1139. *   If a given ray intersect the object's bounding box then add it
  1140. *   to the priority queue.
  1141. *
  1142. * CHANGES
  1143. *
  1144. *   Sep 1994 : Pass bounding box seperately.
  1145. *              This is needed for the vista/light buffer. [DB]
  1146. *
  1147. *   Sep 1994 : Added code to insert infinte objects without testing. [DB]
  1148. *
  1149. ******************************************************************************/
  1150.  
  1151. void Check_And_Enqueue(Queue, Node, BBox, rayinfo)
  1152. PRIORITY_QUEUE *Queue;
  1153. BBOX_TREE *Node;
  1154. BBOX *BBox;
  1155. RAYINFO *rayinfo;
  1156. {
  1157.   DBL tmin, tmax;
  1158.   DBL dmin, dmax;
  1159.  
  1160.   if (Node->Infinite)
  1161.   {
  1162.     /* Set intersection depth to -Max_Distance. */
  1163.  
  1164.     dmin = -Max_Distance;
  1165.   }
  1166.   else
  1167.   {
  1168.     Increase_Counter(stats[nChecked]);
  1169.  
  1170.     if (rayinfo->nonzero[X])
  1171.     {
  1172.       if (rayinfo->positive[X])
  1173.       {
  1174.         dmin = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) *  rayinfo->slab_den[X];
  1175.  
  1176.         dmax = dmin + (BBox->Lengths[X]  * rayinfo->slab_den[X]);
  1177.  
  1178.         if (dmax < EPSILON) return;
  1179.       }
  1180.       else
  1181.       {
  1182.         dmax = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) * rayinfo->slab_den[X];
  1183.  
  1184.         if (dmax < EPSILON) return;
  1185.  
  1186.         dmin = dmax + (BBox->Lengths[X]  * rayinfo->slab_den[X]);
  1187.       }
  1188.  
  1189.       if (dmin > dmax) return;
  1190.     }
  1191.     else
  1192.     {
  1193.       if ((rayinfo->slab_num[X] < BBox->Lower_Left[X]) ||
  1194.           (rayinfo->slab_num[X] > BBox->Lengths[X] + BBox->Lower_Left[X]))
  1195.       {
  1196.         return;
  1197.       }
  1198.  
  1199.       dmin = -BOUND_HUGE;
  1200.       dmax = BOUND_HUGE;
  1201.     }
  1202.  
  1203.     if (rayinfo->nonzero[Y])
  1204.     {
  1205.       if (rayinfo->positive[Y])
  1206.       {
  1207.         tmin = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y];
  1208.  
  1209.         tmax = tmin + (BBox->Lengths[Y]  * rayinfo->slab_den[Y]);
  1210.       }
  1211.       else
  1212.       {
  1213.         tmax = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y];
  1214.  
  1215.         tmin = tmax + (BBox->Lengths[Y]  * rayinfo->slab_den[Y]);
  1216.       }
  1217.  
  1218.       /*
  1219.        * Unwrap the logic - do the dmin and dmax checks only when tmin and
  1220.        * tmax actually affect anything, also try to escape ASAP. Better
  1221.        * yet, fold the logic below into the two branches above so as to
  1222.        *  compute only what is needed.
  1223.        */
  1224.  
  1225.       /*
  1226.        * You might even try tmax < EPSILON first (instead of second) for an
  1227.        * early quick out.
  1228.        */
  1229.  
  1230.       if (tmax < dmax)
  1231.       {
  1232.         if (tmax < EPSILON) return;
  1233.  
  1234.         /* check bbox only if tmax changes dmax */
  1235.  
  1236.         if (tmin > dmin)
  1237.         {
  1238.           if (tmin > tmax) return;
  1239.  
  1240.           /* do this last in case it's not needed! */
  1241.  
  1242.           dmin = tmin;
  1243.         }
  1244.         else
  1245.         {
  1246.           if (dmin > tmax) return;
  1247.         }
  1248.  
  1249.         /* do this last in case it's not needed! */
  1250.  
  1251.         dmax = tmax;
  1252.       }
  1253.       else
  1254.       {
  1255.         if (tmin > dmin)
  1256.         {
  1257.           if (tmin > dmax) return;
  1258.           
  1259.           /* do this last in case it's not needed! */
  1260.           
  1261.           dmin = tmin;
  1262.         }
  1263.  
  1264.         /* else nothing needs to happen, since dmin and dmax did not change! */
  1265.       }
  1266.     }
  1267.     else
  1268.     {
  1269.       if ((rayinfo->slab_num[Y] < BBox->Lower_Left[Y]) ||
  1270.           (rayinfo->slab_num[Y] > BBox->Lengths[Y] + BBox->Lower_Left[Y]))
  1271.       {
  1272.         return;
  1273.       }
  1274.     }
  1275.     
  1276.     if (rayinfo->nonzero[Z])
  1277.     {
  1278.       if (rayinfo->positive[Z])
  1279.       {
  1280.         tmin = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z];
  1281.         
  1282.         tmax = tmin + (BBox->Lengths[Z]  * rayinfo->slab_den[Z]);
  1283.       }
  1284.       else
  1285.       {
  1286.         tmax = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z];
  1287.  
  1288.         tmin = tmax + (BBox->Lengths[Z]  * rayinfo->slab_den[Z]);
  1289.       }
  1290.  
  1291.       if (tmax < dmax)
  1292.       {
  1293.         if (tmax < EPSILON) return;
  1294.  
  1295.         /* check bbox only if tmax changes dmax */
  1296.  
  1297.         if (tmin > dmin)
  1298.         {
  1299.           if (tmin > tmax) return;
  1300.  
  1301.           /* do this last in case it's not needed! */
  1302.  
  1303.           dmin = tmin;
  1304.         }
  1305.         else
  1306.         {
  1307.           if (dmin > tmax) return;
  1308.         }
  1309.       }
  1310.       else
  1311.       {
  1312.         if (tmin > dmin)
  1313.         {
  1314.           if (tmin > dmax) return;
  1315.  
  1316.           /* do this last in case it's not needed! */
  1317.  
  1318.           dmin = tmin;
  1319.         }
  1320.  
  1321.         /* else nothing needs to happen, since dmin and dmax did not change! */
  1322.       }
  1323.     }
  1324.     else
  1325.     {
  1326.       if ((rayinfo->slab_num[Z] < BBox->Lower_Left[Z]) ||
  1327.           (rayinfo->slab_num[Z] > BBox->Lengths[Z] + BBox->Lower_Left[Z]))
  1328.       {
  1329.         return;
  1330.       }
  1331.     }
  1332.  
  1333.     Increase_Counter(stats[nEnqueued]);
  1334.   }
  1335.  
  1336.   priority_queue_insert(Queue, dmin, Node);
  1337. }
  1338.  
  1339.  
  1340.  
  1341. /*****************************************************************************
  1342. *
  1343. * FUNCTION
  1344. *
  1345. *   Create_Rayinfo
  1346. *
  1347. * INPUT
  1348. *
  1349. *   Ray     - Current ray
  1350. *   rayinfo - Rayinfo structure
  1351. *   
  1352. * OUTPUT
  1353. *
  1354. *   rayinfo
  1355. *   
  1356. * RETURNS
  1357. *   
  1358. * AUTHOR
  1359. *
  1360. *   Dieter Bayer
  1361. *   
  1362. * DESCRIPTION
  1363. *
  1364. *   Calculate the rayinfo structure for a given ray. It's need for
  1365. *   intersection the ray with bounding boxes.
  1366. *
  1367. * CHANGES
  1368. *
  1369. *   May 1994 : Creation. (Extracted from Intersect_BBox_Tree)
  1370. *
  1371. ******************************************************************************/
  1372.  
  1373. void Create_Rayinfo(Ray, rayinfo)
  1374. RAY *Ray;
  1375. RAYINFO *rayinfo;
  1376. {
  1377.   DBL t;
  1378.  
  1379.   /* Create the direction vectors for this ray */
  1380.  
  1381.   Assign_Vector(rayinfo->slab_num, Ray->Initial);
  1382.  
  1383.   if ((rayinfo->nonzero[X] = ((t = Ray->Direction[X]) != 0.0)) != 0)
  1384.   {
  1385.     rayinfo->slab_den[X] = 1.0 / t;
  1386.  
  1387.     rayinfo->positive[X] = (Ray->Direction[X] > 0.0);
  1388.   }
  1389.  
  1390.   if ((rayinfo->nonzero[Y] = ((t = Ray->Direction[Y]) != 0.0)) != 0)
  1391.   {
  1392.     rayinfo->slab_den[Y] = 1.0 / t;
  1393.  
  1394.     rayinfo->positive[Y] = (Ray->Direction[Y] > 0.0);
  1395.   }
  1396.  
  1397.   if ((rayinfo->nonzero[Z] = ((t = Ray->Direction[Z]) != 0.0)) != 0)
  1398.   {
  1399.     rayinfo->slab_den[Z] = 1.0 / t;
  1400.  
  1401.     rayinfo->positive[Z] = (Ray->Direction[Z] > 0.0);
  1402.   }
  1403. }
  1404.  
  1405.  
  1406.  
  1407. /*****************************************************************************
  1408. *
  1409. * FUNCTION
  1410. *
  1411. *   create_bbox_node
  1412. *
  1413. * INPUT
  1414. *
  1415. *   size - Number of subnodes
  1416. *
  1417. * OUTPUT
  1418. *
  1419. * RETURNS
  1420. *
  1421. *   BBOX_TREE * - New node
  1422. *
  1423. * AUTHOR
  1424. *
  1425. *   Alexander Enzmann
  1426. *   
  1427. * DESCRIPTION
  1428. *
  1429. *   -
  1430. *
  1431. * CHANGES
  1432. *
  1433. *   -
  1434. *
  1435. ******************************************************************************/
  1436.  
  1437. static BBOX_TREE *create_bbox_node(size)
  1438. int size;
  1439. {
  1440.   BBOX_TREE *New;
  1441.  
  1442.   New = (BBOX_TREE *)POV_MALLOC(sizeof(BBOX_TREE), "bounding box node");
  1443.  
  1444.   New->Infinite = FALSE;
  1445.  
  1446.   New->Entries = size;
  1447.  
  1448.   Make_BBox(New->BBox, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  1449.  
  1450.   if (size)
  1451.   {
  1452.     New->Node = (BBOX_TREE **)POV_MALLOC(size*sizeof(BBOX_TREE *), "bounding box node");
  1453.   }
  1454.   else
  1455.   {
  1456.     New->Node = NULL;
  1457.   }
  1458.  
  1459.   return (New);
  1460. }
  1461.  
  1462.  
  1463.  
  1464. /*****************************************************************************
  1465. *
  1466. * FUNCTION
  1467. *
  1468. *   compboxes
  1469. *
  1470. * INPUT
  1471. *
  1472. *   in_a, in_b - Elements to compare
  1473. *
  1474. * OUTPUT
  1475. *
  1476. * RETURNS
  1477. *
  1478. *   int - result of comparison
  1479. *
  1480. * AUTHOR
  1481. *
  1482. *   Alexander Enzmann
  1483. *
  1484. * DESCRIPTION
  1485. *
  1486. *   -
  1487. *
  1488. * CHANGES
  1489. *
  1490. *   Sep 1994 : Removed test for infinite objects because it's obsolete. [DB]
  1491. *
  1492. ******************************************************************************/
  1493.  
  1494. static int CDECL compboxes(in_a, in_b)
  1495. CONST void *in_a;
  1496. CONST void *in_b;
  1497. {
  1498.   BBOX *a, *b;
  1499.   BBOX_VAL am, bm;
  1500.  
  1501.   a = &((*(BBOX_TREE **)in_a)->BBox);
  1502.   b = &((*(BBOX_TREE **)in_b)->BBox);
  1503.  
  1504.   am = 2.0 * a->Lower_Left[Axis] + a->Lengths[Axis];
  1505.   bm = 2.0 * b->Lower_Left[Axis] + b->Lengths[Axis];
  1506.  
  1507.   if (am < bm)
  1508.   {
  1509.     return (-1);
  1510.   }
  1511.   else
  1512.   {
  1513.     if (am == bm)
  1514.     {
  1515.       return (0);
  1516.     }
  1517.     else
  1518.     {
  1519.       return (1);
  1520.     }
  1521.   }
  1522. }
  1523.  
  1524.  
  1525.  
  1526. /*****************************************************************************
  1527. *
  1528. * FUNCTION
  1529. *
  1530. *   find_axis
  1531. *
  1532. * INPUT
  1533. *
  1534. *   Finite      - Array of finite elements
  1535. *   first, last - Position of elements
  1536. *
  1537. * OUTPUT
  1538. *   
  1539. * RETURNS
  1540. *
  1541. *   int - Axis to sort along
  1542. *   
  1543. * AUTHOR
  1544. *
  1545. *   Alexander Enzmann
  1546. *   
  1547. * DESCRIPTION
  1548. *
  1549. *   Find the axis along which the elements will be sorted.
  1550. *
  1551. * CHANGES
  1552. *
  1553. *   Sep 1994 : Initialize local variable which. [DB]
  1554. *
  1555. ******************************************************************************/
  1556.  
  1557. static int find_axis(Finite, first, last)
  1558. BBOX_TREE **Finite;
  1559. long first, last;
  1560. {
  1561.   int which = X;
  1562.   long i;
  1563.   DBL e, d = -BOUND_HUGE;
  1564.   VECTOR mins, maxs;
  1565.   BBOX *bbox;
  1566.  
  1567.   Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1568.   Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1569.  
  1570.   for (i = first; i < last; i++)
  1571.   {
  1572.     bbox = &(Finite[i]->BBox);
  1573.  
  1574.     if (bbox->Lower_Left[X] < mins[X])
  1575.     {
  1576.       mins[X] = bbox->Lower_Left[X];
  1577.     }
  1578.  
  1579.     if (bbox->Lower_Left[X] + bbox->Lengths[X] > maxs[X])
  1580.     {
  1581.       maxs[X] = bbox->Lower_Left[X];
  1582.     }
  1583.  
  1584.     if (bbox->Lower_Left[Y] < mins[Y])
  1585.     {
  1586.       mins[Y] = bbox->Lower_Left[Y];
  1587.     }
  1588.  
  1589.     if (bbox->Lower_Left[Y] + bbox->Lengths[Y] > maxs[Y])
  1590.     {
  1591.       maxs[Y] = bbox->Lower_Left[Y];
  1592.     }
  1593.  
  1594.     if (bbox->Lower_Left[Z] < mins[Z])
  1595.     {
  1596.       mins[Z] = bbox->Lower_Left[Z];
  1597.     }
  1598.  
  1599.     if (bbox->Lower_Left[Z] + bbox->Lengths[Z] > maxs[Z])
  1600.     {
  1601.       maxs[Z] = bbox->Lower_Left[Z];
  1602.     }
  1603.   }
  1604.  
  1605.   e = maxs[X] - mins[X];
  1606.  
  1607.   if (e > d)
  1608.   {
  1609.     d = e;  which = X;
  1610.   }
  1611.  
  1612.   e = maxs[Y] - mins[Y];
  1613.  
  1614.   if (e > d)
  1615.   {
  1616.     d = e;  which = Y;
  1617.   }
  1618.  
  1619.   e = maxs[Z] - mins[Z];
  1620.  
  1621.   if (e > d)
  1622.   {
  1623.     which = Z;
  1624.   }
  1625.  
  1626.   return (which);
  1627. }
  1628.  
  1629.  
  1630.  
  1631. /*****************************************************************************
  1632. *
  1633. * FUNCTION
  1634. *
  1635. *   calc_bbox
  1636. *
  1637. * INPUT
  1638. *   
  1639. * OUTPUT
  1640. *   
  1641. * RETURNS
  1642. *   
  1643. * AUTHOR
  1644. *
  1645. *   Alexander Enzmann
  1646. *   
  1647. * DESCRIPTION
  1648. *
  1649. *   Calculate the bounding box containing Finite[first] through Finite[last-1].
  1650. *
  1651. * CHANGES
  1652. *
  1653. *   -
  1654. *
  1655. ******************************************************************************/
  1656.  
  1657. static void calc_bbox(BBox, Finite, first, last)
  1658. BBOX *BBox;
  1659. BBOX_TREE **Finite;
  1660. long first, last;
  1661. {
  1662.   long i;
  1663.   DBL tmin, tmax;
  1664.   VECTOR bmin, bmax;
  1665.   BBOX *bbox;
  1666.  
  1667.   COOPERATE_1
  1668.  
  1669.   Make_Vector(bmin, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1670.   Make_Vector(bmax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1671.  
  1672.   for (i = first; i < last; i++)
  1673.   {
  1674.     bbox = &(Finite[i]->BBox);
  1675.  
  1676.     tmin = bbox->Lower_Left[X];
  1677.     tmax = tmin + bbox->Lengths[X];
  1678.  
  1679.     if (tmin < bmin[X]) { bmin[X] = tmin; }
  1680.     if (tmax > bmax[X]) { bmax[X] = tmax; }
  1681.  
  1682.     tmin = bbox->Lower_Left[Y];
  1683.     tmax = tmin + bbox->Lengths[Y];
  1684.  
  1685.     if (tmin < bmin[Y]) { bmin[Y] = tmin; }
  1686.     if (tmax > bmax[Y]) { bmax[Y] = tmax; }
  1687.  
  1688.     tmin = bbox->Lower_Left[Z];
  1689.     tmax = tmin + bbox->Lengths[Z];
  1690.  
  1691.     if (tmin < bmin[Z]) { bmin[Z] = tmin; }
  1692.     if (tmax > bmax[Z]) { bmax[Z] = tmax; }
  1693.   }
  1694.  
  1695.   Make_BBox_from_min_max(*BBox, bmin, bmax);
  1696. }
  1697.  
  1698.  
  1699.  
  1700. /*****************************************************************************
  1701. *
  1702. * FUNCTION
  1703. *
  1704. *   build_area_table
  1705. *
  1706. * INPUT
  1707. *   
  1708. * OUTPUT
  1709. *   
  1710. * RETURNS
  1711. *   
  1712. * AUTHOR
  1713. *
  1714. *   Alexander Enzmann
  1715. *   
  1716. * DESCRIPTION
  1717. *
  1718. *   Generates a table of bound box surface areas.
  1719. *
  1720. * CHANGES
  1721. *
  1722. *   -
  1723. *
  1724. ******************************************************************************/
  1725.  
  1726. static void build_area_table(Finite, a, b, areas)
  1727. BBOX_TREE **Finite;
  1728. long a, b;
  1729. DBL *areas;
  1730. {
  1731.   long i, imin, dir;
  1732.   DBL tmin, tmax;
  1733.   VECTOR bmin, bmax, len;
  1734.   BBOX *bbox;
  1735.  
  1736.   if (a < b)
  1737.   {
  1738.     imin = a;  dir =  1;
  1739.   }
  1740.   else
  1741.   {
  1742.     imin = b;  dir = -1;
  1743.   }
  1744.  
  1745.   Make_Vector(bmin, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1746.   Make_Vector(bmax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1747.  
  1748.   for (i = a; i != (b + dir); i += dir)
  1749.   {
  1750.     bbox = &(Finite[i]->BBox);
  1751.  
  1752.     tmin = bbox->Lower_Left[X];
  1753.     tmax = tmin + bbox->Lengths[X];
  1754.  
  1755.     if (tmin < bmin[X]) { bmin[X] = tmin; }
  1756.     if (tmax > bmax[X]) { bmax[X] = tmax; }
  1757.  
  1758.     tmin = bbox->Lower_Left[Y];
  1759.     tmax = tmin + bbox->Lengths[Y];
  1760.  
  1761.     if (tmin < bmin[Y]) { bmin[Y] = tmin; }
  1762.     if (tmax > bmax[Y]) { bmax[Y] = tmax; }
  1763.  
  1764.     tmin = bbox->Lower_Left[Z];
  1765.     tmax = tmin + bbox->Lengths[Z];
  1766.  
  1767.     if (tmin < bmin[Z]) { bmin[Z] = tmin; }
  1768.     if (tmax > bmax[Z]) { bmax[Z] = tmax; }
  1769.  
  1770.     VSub(len, bmax, bmin);
  1771.  
  1772.     areas[i - imin] = len[X] * (len[Y] + len[Z]) + len[Y] * len[Z];
  1773.   }
  1774. }
  1775.  
  1776.  
  1777.  
  1778. /*****************************************************************************
  1779. *
  1780. * FUNCTION
  1781. *
  1782. *   sort_and_split
  1783. *
  1784. * INPUT
  1785. *
  1786. * OUTPUT
  1787. *
  1788. * RETURNS
  1789. *
  1790. * AUTHOR
  1791. *
  1792. *   Alexander Enzmann
  1793. *
  1794. * DESCRIPTION
  1795. *
  1796. *   -
  1797. *
  1798. * CHANGES
  1799. *
  1800. *   -
  1801. *
  1802. ******************************************************************************/
  1803.  
  1804. static int sort_and_split(Root, Finite, nFinite, first, last)
  1805. BBOX_TREE **Root;
  1806. BBOX_TREE **Finite;
  1807. long *nFinite, first, last;
  1808. {
  1809.   BBOX_TREE *cd;
  1810.   long size, i, best_loc;
  1811.   DBL *area_left, *area_right;
  1812.   DBL best_index, new_index;
  1813.  
  1814.   Axis = find_axis(Finite, first, last);
  1815.  
  1816.   size = last - first;
  1817.  
  1818.   if (size <= 0)
  1819.   {
  1820.     return (1);
  1821.   }
  1822.  
  1823.   /*
  1824.    * Actually, we could do this faster in several ways. We could use a
  1825.    * logn algorithm to find the median along the given axis, and then a
  1826.    * linear algorithm to partition along the axis. Oh well.
  1827.    */
  1828.  
  1829.   QSORT((void *)(&Finite[first]), (unsigned long)size, sizeof(BBOX_TREE *), compboxes);
  1830.  
  1831.   /*
  1832.    * area_left[] and area_right[] hold the surface areas of the bounding
  1833.    * boxes to the left and right of any given point. E.g. area_left[i] holds
  1834.    * the surface area of the bounding box containing Finite 0 through i and
  1835.    * area_right[i] holds the surface area of the box containing Finite
  1836.    * i through size-1.
  1837.    */
  1838.  
  1839.   area_left = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");
  1840.   area_right = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");
  1841.  
  1842.   /* Precalculate the areas for speed. */
  1843.  
  1844.   build_area_table(Finite, first, last - 1, area_left);
  1845.   build_area_table(Finite, last - 1, first, area_right);
  1846.  
  1847.   best_index = area_right[0] * (size - 3.0);
  1848.  
  1849.   best_loc = -1;
  1850.  
  1851.   /*
  1852.    * Find the most effective point to split. The best location will be
  1853.    * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2
  1854.    * are the number of objects in the two groups and A1 and A2 are the
  1855.    * surface areas of the bounding boxes of the two groups.
  1856.    */
  1857.  
  1858.   for (i = 0; i < size - 1; i++)
  1859.   {
  1860.     new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1];
  1861.  
  1862.     if (new_index < best_index)
  1863.     {
  1864.       best_index = new_index;
  1865.       best_loc = i + first;
  1866.     }
  1867.   }
  1868.  
  1869.   POV_FREE(area_left);
  1870.   POV_FREE(area_right);
  1871.  
  1872.   /*
  1873.    * Stop splitting if the BUNCHING_FACTOR is reached or
  1874.    * if splitting stops being effective.
  1875.    */
  1876.  
  1877.   if ((size <= BUNCHING_FACTOR) || (best_loc < 0))
  1878.   {
  1879.     cd = create_bbox_node(size);
  1880.       
  1881.     for (i = 0; i < size; i++)
  1882.     {
  1883.       cd->Node[i] = Finite[first+i];
  1884.     }
  1885.  
  1886.     calc_bbox(&(cd->BBox), Finite, first, last);
  1887.  
  1888.     *Root = (BBOX_TREE *)cd;
  1889.  
  1890.     if (*nFinite > maxfinitecount)
  1891.     {
  1892.       /* Prim array overrun, increase array by 50%. */
  1893.  
  1894.       maxfinitecount = 1.5 * maxfinitecount;
  1895.  
  1896.       /* For debugging only. */
  1897.  
  1898.       Debug_Info("Reallocing Finite to %d\n", maxfinitecount);
  1899.  
  1900.       Finite = (BBOX_TREE **)POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes");
  1901.     }
  1902.  
  1903.     Finite[*nFinite] = cd;
  1904.  
  1905.     (*nFinite)++;
  1906.  
  1907.     return (1);
  1908.   }
  1909.   else
  1910.   {
  1911.     sort_and_split(Root, Finite, nFinite, first, best_loc + 1);
  1912.  
  1913.     sort_and_split(Root, Finite, nFinite, best_loc + 1, last);
  1914.  
  1915.     return (0);
  1916.   }
  1917. }
  1918.  
  1919.